﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using TestByWire.Test.Fakes;

namespace TestByWire.Test
{
	[TestClass]
	public class Integration : TestTarget<MyTargetClass>
	{
		[TestInitialize]
		public void Init()
		{
			Scenario.Is(GreenFlow);
		}

		[TestMethod]
		public void DoTheBddStyle()
		{
			Given.That<IDbAccess>(x => x.GetUser()).Returns(new UserInfo{Name="Foo"});
			
			When.Calling.DoSomething();

			Then<IDbAccess>.Should(x => x.StoreNewSalary("Foo", 50));
		}

		[TestMethod]
		public void DoTheBddStyle2()
		{
			Given.That<IDbAccess>(x => x.GetUser()).Returns(new UserInfo { Name = "Foo" });

			When.Calling.DoSomething();

			Then<IDbAccess>.Should(x => x.GetCurrentSalary("Foo"));
		}

		[TestMethod]
		public void DoTheBddStyle3()
		{
			Given.That<ICalculate>(x => x.Calc()).Returns(100);

			When.Calling.DoSomething();

			Then<IDbAccess>.Should(x=>x.StoreNewSalary(null, 120));
		}

		[TestMethod]
		public void DoTheBddStyle4()
		{
			Given.That<IDbAccess>(x => x.GetCurrentSalary(null)).Returns(100);

			When.Calling.DoSomething();

			Then<IDbAccess>.Should(x => x.StoreNewSalary(null, 130));
		}

		[TestMethod]
		public void DoTheBddStyle5()
		{
			Given.That<ICalculate>(x => x.Calc()).Returns(100);
			Given.That<IDbAccess>(x => x.GetUser()).Returns(new UserInfo { Name = "Foo" });
			Given.That<IDbAccess>(x => x.GetCurrentSalary("Foo")).Returns(50);

			When.Calling.DoSomething();

			Then<IDbAccess>.Should(x => x.StoreNewSalary("Foo", 150));
		}

		private static void GreenFlow()
		{
			A.CallTo<IDbAccess>(x => x.GetUser()).Returns(new UserInfo());
			A.CallTo<IDbAccess>(x => x.GetCurrentSalary(null)).Returns(20);
			A.CallTo<ICalculate>(x => x.Calc()).Returns(30);
		}
	}

	public class MyTargetClass
	{
		private readonly IDbAccess _dbAccess;
		private readonly ICalculate _calc;

		public MyTargetClass(IDbAccess dbAccess, ICalculate calc)
		{
			_dbAccess = dbAccess;
			_calc = calc;
		}

		public void DoSomething()
		{
			UserInfo info = _dbAccess.GetUser();
			int salery = _dbAccess.GetCurrentSalary(info.Name);
			int calcVal = _calc.Calc();
			_dbAccess.StoreNewSalary(info.Name, salery + calcVal);
		}
	}

	public class UserInfo
	{
		public string Name;
	}
}
